package com.tyx.chargingpile.service;

import com.tyx.chargingpile.handler.ChargingHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
 * 前置服务
 */
@Service
public class ChargingService {

    //连接处理group
    private EventLoopGroup boss = new NioEventLoopGroup();
    //事件处理group
    private EventLoopGroup worker = new NioEventLoopGroup();

    @Value("${netty.server.port}")
    private int port;

    private ServerSocketChannel serverSocketChannel;

    public void bind(MessageFactoryService messageFactoryService) {
        //服务端要建立两个group，一个负责接收客户端的连接，一个负责处理数据传输
        ServerBootstrap bootstrap = new ServerBootstrap();
        // 绑定处理group
        bootstrap.group(boss, worker).channel(NioServerSocketChannel.class)
                //保持连接数
                .option(ChannelOption.SO_BACKLOG, 10240)
                //有数据立即发送
                .option(ChannelOption.TCP_NODELAY, false)
                //保持连接
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                //处理新连接
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel sc) throws Exception {
                        // 增加任务处理
                        ChannelPipeline p = sc.pipeline();
                        p.addLast(
//										//使用了netty自带的编码器和解码器
										//new StringDecoder(),
										//new StringEncoder(),
                                new LengthFieldBasedFrameDecoder( 65536, 2, 2, 1, 0, true),
                                //new ChargingProtocolDecoder(),
                                //心跳检测，读超时，写超时，读写超时
                                //new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS),
                                //自定义的处理器
                                new ChargingHandler(messageFactoryService));
                    }
                });

        //绑定端口，同步等待成功
        ChannelFuture future;
        try {
            future = bootstrap.bind(port).sync();
            if (future.isSuccess()) {
                serverSocketChannel = (ServerSocketChannel) future.channel();
                LOGGER.info("服务端启动成功，端口："+port);
            } else {
                LOGGER.info("服务端启动失败！");
            }
            //等待服务监听端口关闭,就是由于这里会将线程阻塞，导致无法发送信息，所以我这里开了线程
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            //优雅地退出，释放线程池资源
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

    private final static Logger LOGGER = LoggerFactory.getLogger(ChargingService.class);

}
